package org.chaiyi.template.core.framework.redis;

import lombok.RequiredArgsConstructor;
import org.chaiyi.template.core.common.util.ProtostuffUtil;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.time.Duration;
import java.time.temporal.ChronoUnit;

@Component
@RequiredArgsConstructor
public class RedisUtils {
    private final ReactiveRedisTemplate<String, byte[]> redisTemplate;

    public <T> Mono<Boolean> set(String key, T value) {
        byte[] bytes = ProtostuffUtil.serialize(value);
        return redisTemplate.opsForValue().set(key, bytes);
    }

    public <T> Mono<Boolean> set(String key, T value, long exp, ChronoUnit timeUnit) {
        byte[] bytes = ProtostuffUtil.serialize(value);
        return redisTemplate.opsForValue().set(key, bytes, Duration.of(exp, timeUnit));
    }

    public <T> Mono<Boolean> setNx(String key, T value, long exp, ChronoUnit timeUnit) {
        byte[] bytes = ProtostuffUtil.serialize(value);
        return redisTemplate.opsForValue().setIfAbsent(key, bytes, Duration.of(exp, timeUnit));
    }

    public Mono<Boolean> delete(String key) {
        return redisTemplate.opsForValue().delete(key);
    }

    public <T> Mono<T> get(String key, Class<T> tClass) {
        return redisTemplate.opsForValue().get(key)
                .map(bytes -> ProtostuffUtil.deserialize(bytes, tClass));
    }

    public Mono<Long> count(String prefix) {
        return keys(prefix).count();
    }

    public Flux<String> keys(String prefix) {
        return redisTemplate.keys(prefix);
    }

    public Mono<Long> deleteAll(String prefix) {
        return redisTemplate.delete(keys(prefix));
    }
}
